//
//  KLHistoricalRateChartView.m
//  KLCurrency
//
//  Created by apple on 2018/1/4.
//  Copyright © 2018年 bonc. All rights reserved.
//

#import "KLHistoricalRateChartView.h"
#import "KLCurveView.h"
#import "KLHistoricalRate.h"
#import "Masonry.h"

static const CGFloat noticeLabelWidth = 300.0f; //底部分析标签
static const CGFloat noticeLabelHeight = 30.0f;//底部分析标签

static const CGFloat analysisLabelMarginTop = 16.0f; //底部分析标签
static const CGFloat analysisLabelHeight = 16.0f;//底部分析标签
static const CGFloat analysisLabelMarginBottom = 16.0f;//底部分析标签
static const CGFloat analysisLabelFontSize = 13.0f;//底部分析标签

static const CGFloat curveViewHeightScale = 0.30f; //曲线在视图中占比
static const CGFloat presentLabelWidth = 90.0f; //选中点坐标说明标签
static const CGFloat dateLabelHeight = 13.0f; //选中点坐标说明标签
static const CGFloat dateLabelFontSize = 11.0f; //选中点坐标说明标签
static const CGFloat valueLabelHeight = 20.0f; //选中点坐标说明标签
static const CGFloat valueLabelFontSize = 18.0f; //选中点坐标说明标签
static const CGFloat labelPositionYScale = 0.15f; //选中点坐标说明标签
static const CGFloat selectedPointDiameter = 8.0f; //选中点
static const CGFloat selectedPointBorderWidth = 1.0f; //选中点
static const CGFloat lineDashPattern = 3.0f; //选中点虚线

typedef NS_ENUM(NSInteger, TouchActionState) {
    TouchActionStateBegin,
    TouchActionStateMoved,
    TouchActionStateEnded
};

@interface KLHistoricalRateChartView () <KLCurveViewDelegate>

@property (strong, nonatomic) UILabel *maxLabel;//最大值标签
@property (strong, nonatomic) UILabel *minLabel;//最小值标签
@property (strong, nonatomic) UILabel *currentLabel;//当前值标签
@property (strong, nonatomic) UILabel *noticeLabel;//提示标签

@property (strong, nonatomic) UILabel *dateLabel;//选中点的日期标签
@property (strong, nonatomic) UILabel *valueLabel;//选中后的值标签
@property (strong, nonatomic) CAShapeLayer *dashedLayer;//选中点的纵向虚线
@property (strong, nonatomic) CAShapeLayer *selectedPoint;//选中的点

@property (copy, nonatomic) UIColor *defaultFontColor;
@property (strong, nonatomic) KLCurveView *curve;

@property (assign, nonatomic) BOOL reverse;

@property (assign, nonatomic) BOOL haveCurve;//有没有曲线
@property (copy, nonatomic) NSArray <NSNumber *> *dataBuffer;//用于临时存储所有汇率值
@property (copy, nonatomic) NSArray *positionYArray;

@property (strong, nonatomic) UIActivityIndicatorView *indicator;

@end

@implementation KLHistoricalRateChartView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setupUI];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self setupUI];
    }
    return self;
}

- (void)setupUI {
    //分析标签背景视图
    UIView *analysisBgView = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - analysisLabelHeight - analysisLabelMarginBottom - analysisLabelMarginTop, self.frame.size.width, analysisLabelHeight + analysisLabelMarginBottom + analysisLabelMarginTop)];
    analysisBgView.backgroundColor = UIColorFromRGB(0xF2F4F7);
    [self addSubview:analysisBgView];
    
    CGFloat analysisLabelWidth = self.frame.size.width / 3;
    CGFloat analysisLabelY = self.frame.size.height - analysisLabelHeight- analysisLabelMarginBottom;
    //底部 最大值label、最小值label、当前值label
    UILabel *minLabel = [[UILabel alloc] init];
    minLabel.frame = CGRectMake(0, analysisLabelY, analysisLabelWidth, analysisLabelHeight);
    minLabel.textAlignment = NSTextAlignmentCenter;
    minLabel.font = [UIFont systemFontOfSize:analysisLabelFontSize];
    minLabel.textColor = self.defaultFontColor;
    minLabel.text = @"最低:--------";
    [self addSubview:minLabel];
    self.minLabel = minLabel;
    
    UILabel *currentLabel = [[UILabel alloc] init];
    currentLabel.frame = CGRectMake(analysisLabelWidth, analysisLabelY, analysisLabelWidth, analysisLabelHeight);
    currentLabel.textAlignment = NSTextAlignmentCenter;
    currentLabel.font = [UIFont systemFontOfSize:analysisLabelFontSize];
    currentLabel.textColor = self.defaultFontColor;
    currentLabel.text = @"当前:--------";
    [self addSubview:currentLabel];
    self.currentLabel = currentLabel;
    
    UILabel *maxLabel = [[UILabel alloc] init];
    maxLabel.frame = CGRectMake(analysisLabelWidth*2, analysisLabelY, analysisLabelWidth, analysisLabelHeight);
    maxLabel.textAlignment = NSTextAlignmentCenter;
    maxLabel.font = [UIFont systemFontOfSize:analysisLabelFontSize];
    maxLabel.textColor = self.defaultFontColor;
    maxLabel.text = @"最高:--------";
    [self addSubview:maxLabel];
    self.maxLabel = maxLabel;
    
    //无数据通知
    UILabel *noticeLabel = [[UILabel alloc] init];
    noticeLabel.frame = CGRectMake((kScreenWidth - noticeLabelWidth) *0.5, 50, noticeLabelWidth, noticeLabelHeight);
    noticeLabel.textColor = [UIColor orangeColor];
    noticeLabel.font = [UIFont systemFontOfSize:12.0];
    noticeLabel.textAlignment = NSTextAlignmentCenter;
    [self addSubview:noticeLabel];
    self.noticeLabel = noticeLabel;
}

- (UIActivityIndicatorView *)indicator {
    if (_indicator == nil) {
        _indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        [self addSubview:_indicator];
        [_indicator mas_makeConstraints:^(MASConstraintMaker *make) {
            make.center.mas_equalTo(CGPointMake(0, -self.frame.size.height * curveViewHeightScale / 2));
        }];
    }
    return _indicator;
}

- (void)startLoading {
    [self.indicator startAnimating];
}

- (void)stopLoading {
    [self.indicator stopAnimating];
}

- (void)setState:(KLHistoricalRateState)state {
    _state = state;
    switch (state) {
        case KLHistoricalRateStateNoNetWork:
            self.noticeLabel.text = @"暂无网络，请检查网络设置";
            self.noticeLabel.hidden = NO;
            break;
        case KLHistoricalRateStateRequestFailed:
            self.noticeLabel.text = @"暂无历史数据，请稍后再试";
            self.noticeLabel.hidden = NO;
            break;
        case KLHistoricalRateStateRequestSuccess:
            self.noticeLabel.text = nil;
            self.noticeLabel.hidden = YES;
            break;
        case KLHistoricalRateStateLocalTest:
            self.noticeLabel.text = @"仅用于曲线仿真（本地数据）测试";
            self.noticeLabel.hidden = NO;
            break;
        default:
            break;
    }
}

#pragma mark - curve view delegate

- (void)feedbackPointYArray:(NSArray *)pointYArray {
    self.positionYArray = pointYArray;
}

#pragma mark - touch action
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    if (!_haveCurve) {
        return;
    }
    
    UITouch *touch = [touches anyObject];
    [self setLabelWith:touch withState:TouchActionStateBegin];
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    if (!_haveCurve) {
        return;
    }
    
    UITouch *touch = [touches anyObject];
    [self setLabelWith:touch withState:TouchActionStateMoved];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    if (!_haveCurve) {
        return;
    }
    
    UITouch *touch = [touches anyObject];
    [self setLabelWith:touch withState:TouchActionStateEnded];
}


- (void)setLabelWith:(UITouch *)touch withState:(TouchActionState)state {
    CGPoint point = [touch locationInView:self];
    CGFloat value = point.x / self.frame.size.width * (_dataBuffer.count - 1);
    NSDecimalNumber *num = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%.0f", value]];
    
    NSInteger index = [num integerValue];
    
    if (index < _dataArray.count) {
        KLHistoricalRate *rate = _dataArray[index];
        self.dateLabel.text = rate.date;
        
        if (index < _dataBuffer.count) {
            NSDecimalNumber *num = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%0.6f", [_dataBuffer[index] floatValue]]];
            self.valueLabel.text = [num stringValue];
            self.currentLabel.text = [NSString stringWithFormat:@"当前:%@", num];
        }
    }
    
    if (state == TouchActionStateEnded) {
        self.dateLabel.hidden = YES;
        self.valueLabel.hidden = YES;
        self.dashedLayer.hidden = YES;
        self.selectedPoint.hidden = YES;
        
    } else {
        CGFloat positionX = point.x;
        if (positionX < presentLabelWidth / 2) {
            positionX = presentLabelWidth / 2;
        } else if (positionX > self.frame.size.width - presentLabelWidth / 2) {
            positionX = self.frame.size.width - presentLabelWidth / 2;
        }
        
        self.dateLabel.center =  CGPointMake(positionX, self.dateLabel.center.y);
        self.valueLabel.center = CGPointMake(positionX, self.valueLabel.center.y);
        
        //dashed line
        positionX = 0;
        if (_dataArray.count > 0) {
            CGFloat proportion = index * 1.0 / (_dataArray.count - 1);
            positionX = proportion * self.frame.size.width;
            if (positionX == 0) {
                positionX = 1.0f;
            } else if (positionX >= self.frame.size.width) {
                positionX = self.frame.size.width - 1;
            }
        }
        
        CGFloat positionY = 0;
        if (index < _positionYArray.count) {
            CGFloat value = [_positionYArray[index] floatValue];
            positionY = CGRectGetMinY(_curve.frame) + value;
        } else {
            positionY = [[_positionYArray lastObject] floatValue] + CGRectGetMinY(_curve.frame);
        }
        if (isnan(positionY)) {
            positionY = -1;
        }
        
        [CATransaction begin];
        [CATransaction setDisableActions:YES];
        self.dashedLayer.position = CGPointMake(positionX, self.dashedLayer.position.y);
        self.selectedPoint.position = CGPointMake(positionX, positionY);
        [CATransaction commit];
        
        if (state == TouchActionStateBegin) {
            self.dateLabel.hidden = NO;
            self.valueLabel.hidden = NO;
            self.dashedLayer.hidden = NO;
            self.selectedPoint.hidden = NO;
        }
    }
}

#pragma mark - data lazy initialization

- (void)setDataArray:(NSArray<KLHistoricalRate *> *)dataArray {
    if (dataArray == nil) {
        self.dataBuffer = nil;
        _dataArray = nil;
        _state = KLHistoricalRateStateRequestFailed;
        self.haveCurve = NO;
        return;
    }
    _dataArray = dataArray;
    
    NSMutableArray *array = [NSMutableArray array];
    CGFloat maxValue = 0.0f;
    CGFloat minValue =  CGFLOAT_MAX;
    
    for (KLHistoricalRate *obj in dataArray) {
        if (obj.rate > maxValue) {
            maxValue = obj.rate;
        }
        if (obj.rate < minValue) {
            minValue = obj.rate;
        }
        [array addObject:@(obj.rate)];
    }
    CGFloat currentValue = [dataArray firstObject].rate;
    
    if (maxValue > 0 && minValue < CGFLOAT_MAX && currentValue > 0) {
        [self setLabelWithMaxValue:maxValue minValue:minValue currentValue: currentValue];
        self.dataBuffer = array;
        
        if (_reverse) {
            self.reverse = NO;
            [self reverseCurrencies];
        } else {
            [self setCurveWithMaxValue:maxValue andMinValue:minValue];
        }
    }
}

- (void)clearCurveView {
    [_curve removeFromSuperview];
    _maxLabel.text = nil;
    _minLabel.text = nil;
    _currentLabel.text = nil;
    self.haveCurve = NO;
}

- (void)reverseCurrencies {
    self.reverse = !_reverse;
    if (!_dataBuffer.count) {
        return;
    }
    
    NSMutableArray *tempRateArray = [NSMutableArray array];
    CGFloat maxValue = 0.0f;
    CGFloat minValue = CGFLOAT_MAX;
    CGFloat currentValue = 0.0f;
    
#if CGFLOAT_IS_DOUBLE
    CGFloat val = [[_dataBuffer firstObject] doubleValue];
#else
    CGFloat val = [[_dataBuffer firstObject] floatValue];
#endif
    
    if ( val > 0 && !isnan(val)) {
        currentValue = 1.0000 / val;
    } else {
        currentValue = NAN;
    }
    
    for (NSNumber *num in _dataBuffer) {
        
#if CGFLOAT_IS_DOUBLE
        CGFloat value = [num doubleValue];
#else
        CGFloat value = [num floatValue];
#endif
        
        if (value > 0 && !isnan(val)) {
            value = 1.0000 / value;
            if (value > maxValue) {
                maxValue = value;
            }
            if (value < minValue) {
                minValue = value;
            }
            [tempRateArray addObject:@(value)];
        } else {
            value = NAN;
            [tempRateArray addObject:@(value)];
        }
    }
    
    if (maxValue > 0 && minValue < CGFLOAT_MAX && currentValue > 0) {
        [self setLabelWithMaxValue:maxValue minValue:minValue currentValue:currentValue];
        
        self.dataBuffer = [tempRateArray mutableCopy];
        [self setCurveWithMaxValue:maxValue andMinValue:minValue];
    }
}


#pragma mark - draw curve

- (void)setCurveWithMaxValue:(CGFloat)maxValue andMinValue:(CGFloat)minValue {
    if (_dataBuffer.count > 1) {
        if (_curve != nil) {
            [_curve removeFromSuperview];
            self.curve = nil;
        }
        
        CGFloat height = self.frame.size.height * curveViewHeightScale;
        self.curve = [[KLCurveView alloc] initWithFrame:CGRectMake(0, (self.frame.size.height - height * 1.5) / 2, self.frame.size.width, height)];
        _curve.delegate = self;
        
        NSMutableArray *array = [NSMutableArray array];
        for (NSString *str in _dataBuffer) {
        #if CGFLOAT_IS_DOUBLE
            CGFloat value = [str doubleValue];
        #else
            CGFloat value = [str floatValue];
        #endif
            value = value - minValue;
            if (value < 0) {
                value = 0;
            }
            [array addObject:@(value)];
        }
        _curve.pointsArray = array;
        _curve.rateSpan = maxValue - minValue;
        
        if (fabs(maxValue - minValue)>kMinFloat) {
            //如果最大和最小有差值
            _curve.rateSpan = maxValue - minValue;
        }else {
            //如果最大和最小有无差值 比如所有数据都相同
            _curve.rateSpan = maxValue * 2;
        }
        
        _curve.backgroundColor = [UIColor clearColor];
        [self addSubview:_curve];
        [_curve startDrawCurve];
        
        self.haveCurve = YES;
        [self.dashedLayer removeFromSuperlayer];
        [self.selectedPoint removeFromSuperlayer];
        [self.layer addSublayer:self.selectedPoint];
        [self.layer addSublayer:self.dashedLayer];
    }
}

#pragma mark - UI lazy initialization
//默认字体颜色 OK
- (UIColor *)defaultFontColor {
    if (_defaultFontColor == nil) {
        _defaultFontColor = UIColorFromRGB(0x99A4BF);
    }
    return _defaultFontColor;
}

//选中点值标签 OK
- (UILabel *)valueLabel {
    if (_valueLabel == nil) {
        _valueLabel = [[UILabel alloc] init];
        _valueLabel.bounds = CGRectMake(0, 0, presentLabelWidth, valueLabelHeight);
        _valueLabel.center = CGPointMake(presentLabelWidth / 2, self.frame.size.height * labelPositionYScale - valueLabelHeight/ 2 -20.0f);
        _valueLabel.font = [UIFont systemFontOfSize:valueLabelFontSize];
        _valueLabel.textAlignment = NSTextAlignmentCenter;
        _valueLabel.textColor = UIColorFromRGB(0x4A4A4A);
        [self addSubview:_valueLabel];
    }
    return _valueLabel;
}


//选中点日期标签 OK
- (UILabel *)dateLabel {
    if (_dateLabel == nil) {
        _dateLabel = [[UILabel alloc] init];
        _dateLabel.bounds = CGRectMake(0, 0, presentLabelWidth, dateLabelHeight);
        _dateLabel.center = CGPointMake(presentLabelWidth / 2, self.frame.size.height * labelPositionYScale - dateLabelHeight/2 - valueLabelHeight - 20.0f);
        _dateLabel.font = [UIFont systemFontOfSize:dateLabelFontSize];
        _dateLabel.textAlignment = NSTextAlignmentCenter;
        _dateLabel.textColor = self.defaultFontColor;
        [self addSubview:_dateLabel];
    }
    return _dateLabel;
}

//选中点虚线 OK
- (CAShapeLayer *)dashedLayer {
    if (_dashedLayer == nil) {
        _dashedLayer = [CAShapeLayer layer];
        CGFloat dashedLineHeight = self.frame.size.height - analysisLabelHeight - analysisLabelMarginBottom - analysisLabelMarginTop - CGRectGetMaxY(self.valueLabel.frame) - lineDashPattern;
        _dashedLayer.bounds = CGRectMake(0, 0, 1, dashedLineHeight);
        _dashedLayer.position = CGPointMake(0.5, CGRectGetMaxY(_valueLabel.frame) + dashedLineHeight / 2);
        [_dashedLayer setStrokeColor:[UIColorFromRGB(0xD3D8E6) colorWithAlphaComponent:0.8].CGColor];
        [_dashedLayer setLineWidth:1.0];
        [_dashedLayer setLineDashPattern:@[@(lineDashPattern), @(lineDashPattern)]];
    
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(1, 0)];
        [path addLineToPoint:CGPointMake(1, dashedLineHeight)];
        _dashedLayer.path = path.CGPath;
        
        _dashedLayer.hidden = YES;
        [self.layer addSublayer:_dashedLayer];
    }
    return _dashedLayer;
}

//选中的点 OK
- (CAShapeLayer *)selectedPoint {
    if (_selectedPoint == nil) {
        _selectedPoint = [CAShapeLayer layer];
        _selectedPoint.frame = CGRectMake(0, 0, selectedPointDiameter, selectedPointDiameter);
        [_selectedPoint setFillColor:[UIColor whiteColor].CGColor];
        UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, selectedPointDiameter, selectedPointDiameter)];
        _selectedPoint.path = path.CGPath;
        //点阴影
        CAShapeLayer *shadowlayer = [CAShapeLayer layer];
        shadowlayer.frame = CGRectMake(0, 0, selectedPointDiameter * 1.5, selectedPointDiameter * 1.5);
        shadowlayer.position = CGPointMake(selectedPointDiameter / 2, selectedPointDiameter / 2);
        [shadowlayer setFillColor:[[UIColor blackColor] colorWithAlphaComponent:0.5].CGColor];
        UIBezierPath *shadowCircle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, selectedPointDiameter * 1.5, selectedPointDiameter * 1.5)];
        shadowlayer.path = shadowCircle.CGPath;
        [_selectedPoint addSublayer:shadowlayer];
        //点边框
        CAShapeLayer *borderlayer = [CAShapeLayer layer];
        borderlayer.frame = CGRectMake(0, 0, selectedPointDiameter, selectedPointDiameter);
        borderlayer.position = CGPointMake(selectedPointDiameter / 2, selectedPointDiameter / 2);
        [borderlayer setFillColor:UIColorFromRGB(0x99A4BF).CGColor];
        UIBezierPath *borderCircle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, selectedPointDiameter, selectedPointDiameter)];
        borderlayer.path = borderCircle.CGPath;
        [_selectedPoint addSublayer:borderlayer];
        //点中心白色
        CAShapeLayer *centerlayer = [CAShapeLayer layer];
        centerlayer.frame = CGRectMake(0, 0, selectedPointDiameter-selectedPointBorderWidth*2, selectedPointDiameter-selectedPointBorderWidth*2);
        centerlayer.position = CGPointMake(selectedPointDiameter / 2, selectedPointDiameter / 2);
        [centerlayer setFillColor:[UIColor whiteColor].CGColor];
        UIBezierPath *centerCircle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, selectedPointDiameter-selectedPointBorderWidth*2, selectedPointDiameter-selectedPointBorderWidth*2)];
        centerlayer.path = centerCircle.CGPath;
        [_selectedPoint addSublayer:centerlayer];
        
        _selectedPoint.hidden = YES;
        [self.layer addSublayer:_selectedPoint];
    }
    return _selectedPoint;
}

//设置统计标签值 OK
- (void)setLabelWithMaxValue:(CGFloat)maxValue minValue:(CGFloat)minValue currentValue:(CGFloat)currentValue {
    NSDecimalNumber *max = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%.6f", maxValue]];
    _maxLabel.text = [NSString stringWithFormat:@"最高:%@", max];
//    NSDecimalNumber *current = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%.6f", currentValue]];
//    _currentLabel.text = [NSString stringWithFormat:@"当前:%@", current];
    _currentLabel.text = @"当前:--------";
    NSDecimalNumber *min = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%.6f", minValue]];
    _minLabel.text = [NSString stringWithFormat:@"最低:%@", min];
}



@end
